package com.ccnu.JobHub.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ccnu.JobHub.common.util.Token;
import com.ccnu.JobHub.model.common.Result;
import com.ccnu.JobHub.model.database.*;
import com.ccnu.JobHub.model.request.ImageRequest;
import com.ccnu.JobHub.model.request.LoginRequest;
import com.ccnu.JobHub.model.request.RegisterRequest;
import com.ccnu.JobHub.model.response.SearchUserResponse;
import com.ccnu.JobHub.service.impl.*;
import jakarta.mail.MessagingException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

@RestController
@RequestMapping("auth")
@CrossOrigin("*")
@Slf4j
public class AuthController {
    private final StudentService studentService;
    private final SchoolService schoolService;
    private final StudentTokenService studentTokenService;
    private final CaptchaService captchaService;
    private final EmailService emailService;
    private final ManagerService managerService;

    @Value("${upload.dir}")
    private String uploadDir;

    public AuthController(StudentService studentService, SchoolService schoolService, StudentTokenService studentTokenService, CaptchaService captchaService, EmailService emailService, ManagerService managerService) {
        this.studentService = studentService;
        this.schoolService = schoolService;
        this.studentTokenService = studentTokenService;
        this.captchaService = captchaService;
        this.emailService = emailService;
        this.managerService = managerService;
    }

    /**
     * 登录
     *
     * @return 返回是否登录成功，如果成功，返回一个token
     */
    @PostMapping("login")
    public Result login(@RequestBody LoginRequest loginRequest) {
        log.info("--------------------登录请求--------------------");
//      首先查询student表是否有这个学生，如果有将其打包返回。
        QueryWrapper<Student> queryWrapper = new QueryWrapper<Student>()
                .eq("email", loginRequest.getEmail());
        Student student = studentService.getOne(queryWrapper);
        if (student == null) {
            return Result.error("该用户不存在");
        }

        if (!student.getPassword().equals(loginRequest.getPassword())) {
            return Result.error("密码错误");
        }

        String token = Token.generateNewToken(String.valueOf(student.getStudentId()), false);

        Map<String, Object> data = new HashMap<>();
        data.put("user", student);
        data.put("token", token);

        // 把 token存到数据库中
        if (studentTokenService.getById(student.getStudentId()) == null) {
            studentTokenService.save(new StudentToken(student.getStudentId(), token));
        } else {
            studentTokenService.updateById(new StudentToken(student.getStudentId(), token));
        }
        return Result.success("登录成功", data);
    }
    /**
     * 登录
     *
     * @return 返回是否登录成功，如果成功，返回一个token
     */
    @PostMapping("managerLogin")
    public Result managerLogin(@RequestBody LoginRequest loginRequest) {
        log.info("--------------------管理员登录请求--------------------");
//      首先查询student表是否有这个学生，如果有将其打包返回。
        QueryWrapper<Manager> queryWrapper = new QueryWrapper<Manager>()
                .eq("email", loginRequest.getEmail());
        Manager manager = managerService.getOne(queryWrapper);
        if (manager == null) {
            return Result.error("该用户不存在");
        }

        if (!manager.getPassword().equals(loginRequest.getPassword())) {
            return Result.error("密码错误");
        }

        String token = Token.generateNewToken(String.valueOf(manager.getManagerId()), false);

        Map<String, Object> data = new HashMap<>();
        data.put("user", manager);
        data.put("token", token);
        return Result.success("管理员登录成功", data);
    }

    /**
     * 注册
     *
     * @param registerRequest 需要邮箱，密码，姓名和身份证号来验证学生身份
     * @return 注册成功就返回成功，否则返回失败原因
     */
    @PostMapping("register")
    public Result register(@RequestBody RegisterRequest registerRequest) {
//      查询school表是否有这个人，如果有加入到student表，没有，返回非本校学生
//        System.out.println(registerRequest);
        log.info("--------------------注册请求--------------------");
        QueryWrapper<School> queryWrapper = new QueryWrapper<School>()
                .eq("name", registerRequest.getName())
                .eq("identity_card_number", registerRequest.getIdentity_card_number());
        QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<Student>()
                .eq("email", registerRequest.getEmail());
        School school = schoolService.getOne(queryWrapper);
        Student student = studentService.getOne(studentQueryWrapper);
        if (student != null) {
            return Result.error("该邮箱已注册");
        }
        if (school == null) {
            return Result.error("非本校学生");
        }
        if ("0".equals(school.getRegister())) {
            Student student1 = new Student();
            student1.setStudentId(school.getStudentId());
            student1.setSex('U');
            student1.setAvatar("JobHub/src/main/resources/static/默认头像.jpg");
            student1.setEmail(registerRequest.getEmail());
            student1.setPassword(registerRequest.getPassword());
            student1.setName(registerRequest.getName());
            student1.setNickname(registerRequest.getName());
            studentService.save(student1);
            UpdateWrapper<School> updateWrapper = new UpdateWrapper<School>()
                    .eq("student_id", school.getStudentId());
            school.setRegister("1");
            schoolService.update(school, updateWrapper);
            return Result.success("注册成功");
        } else return Result.error("该用户已注册");
    }


    /**
     * 查询自己的个人信息
     *
     * @param token token
     * @return 返回对应学号的学生信息
     */
    @GetMapping("selfInformation")
    public Result selfInformation(@RequestHeader("token") String token) {
        log.info("--------------------返回个人信息请求--------------------");
        String studentId = Token.inspectOldToken(token);
        Student student = studentService.getById(studentId);
        if (student == null) {
            return Result.error("返回个人信息失败");
        }
        student.setPassword("");
        return Result.success("返回个人信息成功", student);
    }


    /**
     * 修改自己的个人信息
     *
     * @param data 学生信息
     * @return 返回修改个人信息成功
     */
    @PutMapping("modifySelfInfo")
    public Result modifySelfInfo(@RequestBody Student data) {
        log.info("--------------------修改个人信息请求--------------------");
        studentService.updateById(data);
        return Result.success("修改个人信息成功");
    }

    private static void showHeaders(HttpServletRequest request) {
        log.info("--------------------这是请求头--------------------");
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            System.out.println(headerName + ": " + request.getHeader(headerName));
        }
    }

    private static void showParams(HttpServletRequest request) {
        log.info("--------------------这是附带参数列表--------------------");
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + Arrays.toString(entry.getValue()));
        }
    }

    /**
     * post测试
     *
     * @param request     请求
     * @param requestBody 请求体
     * @return Result结果
     */
    @PostMapping("postTest")
    public Result test(HttpServletRequest request, @RequestBody String requestBody) {
        log.info("--------------------Post测试请求--------------------");
        // 获取请求头
        showHeaders(request);
        // 获取参数
        showParams(request);

        // 获取请求体
        log.info("--------------------这是请求主题body--------------------");
        System.out.println("Request Body: " + requestBody);
        return Result.success("测试成功");
    }

    /**
     * get测试
     *
     * @param request 请求
     * @return Result结果
     */
    @GetMapping("getTest")
    public Result test(HttpServletRequest request) {
        log.info("--------------------Get测试请求--------------------");
        // 获取请求头
        showHeaders(request);
        // 获取参数
        showParams(request);
        return Result.success("测试成功");
    }
    /**
     * 上传头像PC端
     * @param token token口令
     * @param avatar 上传的头像
     * @return 一个Result结果
     */
    @PostMapping("avatar2")
    public Result avatar2(@RequestHeader("token") String token ,@RequestParam("avatar") MultipartFile avatar){
        log.info("--------------------上传头像请求--------------------");
        String studentId = Token.inspectOldToken(token);
        Student student = studentService.getById(studentId);

        try {
            String currentWorkingDir = System.getProperty("user.dir");
            Result result = getResult(student);
            if (result != null) return result;
            String filePath;

//            System.out.println(currentWorkingDir);
            String fileName = System.currentTimeMillis() + "_" + avatar.getOriginalFilename();
            filePath = uploadDir + File.separator + fileName;
            Path path = Paths.get(currentWorkingDir, filePath);
            avatar.transferTo(path.toFile());
            student.setAvatar(filePath);
            studentService.saveOrUpdate(student);

            return Result.success("上传头像成功");
        } catch (IOException e) {
            return Result.error("上传头像失败");
        }
    }
    /**
     * 上传头像手机端
     * @param token token口令
     * @param imageRequest 上传的头像数据
     * @return 一个Result结果
     */
    @PostMapping("avatar")
    public Result avatar(@RequestHeader("token") String token ,@RequestBody ImageRequest imageRequest){
        log.info("--------------------上传头像请求--------------------");
        String studentId = Token.inspectOldToken(token);
        Student student = studentService.getById(studentId);

        try {
            Result result = getResult(student);
            if (result != null) return result;
            String filePath;

//            System.out.println(currentWorkingDir);
            // 将Base64数据解码为二进制数据
            byte[] imageData = Base64.decodeBase64(imageRequest.getImageData());
            String fileName = System.currentTimeMillis() + ".jpg";
            filePath = uploadDir + File.separator + fileName;
            // 将解码后的数据写入文件
            try (FileOutputStream fos = new FileOutputStream(filePath)) {
                fos.write(imageData);
            }
            student.setAvatar(filePath);
            studentService.saveOrUpdate(student);

            return Result.success("上传头像成功");
        } catch (IOException e) {
            log.error(String.valueOf(e));
            return Result.error("上传头像失败");
        }
    }

    private static Result getResult(Student student) {
        String currentWorkingDir = System.getProperty("user.dir");
        String filePath = student.getAvatar();
        if (filePath != null && !filePath.isEmpty()){
            Path path = Paths.get(currentWorkingDir, filePath);
            try {
                Files.delete(path);
            } catch (Exception e) {
                System.out.println("文件删除失败: " + e.getMessage());
                return Result.error("原头像删除失败");
            }
        }
        return null;
    }

    /**
     * 获取头像
     * @param studentId 学生id
     * @return Result结果
     */
    @GetMapping("getAvatar")
    public Result getAvatar(@RequestParam("studentId") String studentId){
        log.info("--------------------查看头像请求--------------------");
        log.info("--------------------查看头像请求--------------------");
        Student student = studentService.getById(studentId);
        String avatar = student.getAvatar();
        if (avatar == null || avatar.isEmpty()){
            avatar = "JobHub/src/main/resources/static/默认头像.jpg";
        }
        Path filePath = Paths.get(avatar);
        try {
            // 读取图片文件的输入流
            String base64Image;
            try (InputStream imageStream = Files.newInputStream(filePath)) {
                // 将图片文件转换为Base64字符串
                base64Image = Base64.encodeBase64String(imageStream.readAllBytes());
            }

            // 返回 Result 对象
            return Result.success("返回头像成功", base64Image);
        } catch (IOException e) {
            // 处理异常，例如图片不存在时的情况
            log.error(String.valueOf(e));
            return Result.error("返回头像失败");
        }
    }

    /**
     * 查询他人信息
     * @param studentId 要查询的学生id
     * @return 返回一个Result结果
     */
    @GetMapping("getInformation")
    public Result getInformation(@RequestParam("studentId") String studentId){
        log.info("--------------------查询他人信息请求--------------------");
        Student student = studentService.getById(Integer.valueOf(studentId));
        if (student == null){
            return Result.error("查询他人信息失败");
        }
        student.setPassword("");
        student.setName("");
        return Result.success("查询他人信息成功",student);
    }

    /**
     * 生成随机验证码
     * @return 一个6位数验证码
     */
    private String randomInteger() {
        Random random = new Random();
        StringBuilder stringBuffer = new StringBuilder();
        //生成6位的随机数
        for (int i = 0;i<6;i++){
            int i1 = random.nextInt(10);
            stringBuffer.append(i1);
        }
        return stringBuffer.toString();
    }

    @PostMapping("sendCAPTCHA")
    public Result sendCAPTCHA(@RequestBody Map<String ,String> email) {
        String email2 = email.get("email");
        String CAPTCHA = randomInteger();
        String tempToken = Token.generateNewToken(email2,true);
        Date date = new Date();
        // 使用Calendar对象来修改日期时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date); // 设置Calendar的时间为当前时间

        // 加上5分钟
        calendar.add(Calendar.MINUTE, 5);

        Date newDate = calendar.getTime();

        String htmlContent = """
                <!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <style>
                        body {
                            font-family: Arial, sans-serif;
                            margin: 0;
                            padding: 0;
                            color: #333;
                        }
                        .email-container {
                            width: 100%%;
                            max-width: 600px;
                            margin: 0 auto;
                            padding: 20px;
                            border: 1px solid #ddd;
                            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
                        }
                        .header {
                            text-align: center;
                            font-size: 24px;
                            font-weight: bold;
                            margin-bottom: 20px;
                        }
                        .content {
                            text-align: center;
                        }
                    </style>
                </head>
                <body>
                    <div class="email-container">
                        <div class="header">验证码确认</div>
                        <div class="content">
                            <p>您好！</p>
                            <p>感谢您使用我们的服务。为了确保您的账户安全，请在接下来的操作中输入以下验证码：</p>
                           \s
                            <div style="font-size: 24px; font-weight: bold;">
                                <span id="captcha-code">%s</span>
                            </div>
                           \s
                            <p>请勿将此验证码泄露给他人，并尽快完成验证操作。</p>
                            <p>如果这不是您本人的操作，请忽略此邮件。</p>
                            <p>验证码有效期为5分钟，请尽快验证。</p>
                           \s
                            <p>祝您使用愉快！</p>
                            <p>—— 您的朋友，启航站</p>
                        </div>
                    </div>
                </body>
                </html>""".formatted(CAPTCHA);
        try {

            emailService.sendEmail(email2,"注册验证码",htmlContent);
        } catch (MessagingException e) {
            log.error(String.valueOf(e));
            return Result.error("发送验证码邮件失败");
        }
        Captcha captcha = new Captcha();
        captcha.setToken(tempToken);
        captcha.setCaptcha(CAPTCHA);
        captcha.setDeleteTime(newDate);
        captchaService.save(captcha);
        return Result.success("发送验证码成功",tempToken);
    }

    /**
     * 核实验证码
     * @param token 临时token
     * @param captcha 验证码
     * @return 一个Result结果
     */
    @GetMapping("verifyCAPTCHA")
    public Result verifyCAPTCHA(@RequestHeader("token") String token, @RequestParam("captcha") String captcha){
        log.info("--------------------验证验证码请求--------------------");

        QueryWrapper<Captcha> captchaQueryWrapper = new QueryWrapper<Captcha>()
                .eq("token",token);
        Captcha captcha1 = captchaService.getOne(captchaQueryWrapper);
        if (captcha1 == null){
            return Result.error("验证码已过期");
        }
        else if(captcha1.getCaptcha().equals(captcha)){
            return Result.success("验证通过");
        }
        else {
            return Result.error("验证码错误");
        }
    }

    /**
     * 搜索用户
     * @param search 搜索内容
     * @param page 当前页码
     * @param pageSize 页面大小
     * @return 一个Result结果
     */
    @GetMapping("searchUser")
    public Result searchUser(@RequestParam("search") String search,@RequestParam("page") Integer page,@RequestParam("pageSize") Integer pageSize){
        log.info("--------------------搜索用户请求--------------------");
        QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<Student>()
                .like("nickname",search);
        Page<Student> studentPage =Page.of(page,pageSize);
        Page<Student> p = studentService.page(studentPage,studentQueryWrapper);
        List<Student> students = p.getRecords();
        if (students.isEmpty()){
            return Result.error("未搜索到用户");
        }
        List<SearchUserResponse> searchUserResponses = new ArrayList<>();
        return Optional.of(students).map(studentList -> {
            for(Student student : studentList){
                SearchUserResponse searchUserResponse = new SearchUserResponse();
                searchUserResponse.setNickname(student.getNickname());
                searchUserResponse.setSex(student.getSex());
                searchUserResponse.setStudentId(student.getStudentId());
                searchUserResponse.setBriefIntroduction(student.getBriefIntroduction());
                searchUserResponses.add(searchUserResponse);
            }
            return Result.success("成功搜索用户",searchUserResponses);
        }).orElse(Result.error("未搜索到用户"));
    }
}
